package com.jintian.smart.kernel.autoconfigure.extend.work;

import com.jintian.smart.kernel.autoconfigure.extend.resposity.WorkerIdAssigner;
import com.jintian.smart.kernel.autoconfigure.extend.util.NetUtil;
import com.jintian.smart.kernel.common.util.HomeUtil;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Properties;

public class LocalWorkerIdAssigner implements WorkerIdAssigner {
    private static String WORKER_META_FILE;
    private static final int MAX_WORKER_ID = 1023;
    private static final int SEQUENCE_OFFSET = 1000;

    static {
        WORKER_META_FILE = HomeUtil.getConfigPath() + File.separator + "workid.properties";
    }

    // 读取或初始化 WorkerID 元数据
    private static WorkerMeta readOrInitWorkerMeta() throws IOException {
        Path path = Paths.get(WORKER_META_FILE);
        if (Files.exists(path)) {
            Properties props = new Properties();
            try (InputStream in = Files.newInputStream(path)) {
                props.load(in);
            }
            return new WorkerMeta(
                    Integer.parseInt(props.getProperty("last_worker_id", "0")),
                    Integer.parseInt(props.getProperty("sequence", "0")),
                    props.getProperty("ip_hash", "")
            );
        } else {
            return new WorkerMeta(0, 0, "");
        }
    }

    // 保存 WorkerID 元数据
    private static void saveWorkerMeta(WorkerMeta meta) throws IOException {
        Properties props = new Properties();
        props.setProperty("last_worker_id", String.valueOf(meta.lastWorkerId));
        props.setProperty("sequence", String.valueOf(meta.sequence));
        props.setProperty("ip_hash", meta.ipHash);

        Path path = Paths.get(WORKER_META_FILE);
        Files.createDirectories(path.getParent());
        try (OutputStream out = Files.newOutputStream(path)) {
            props.store(out, "WorkerID Meta Data");
        }
    }

    // 获取当前 IP 的哈希值
    private static String getIpHash() throws Exception {
        String ip = NetUtil.getLocalAddress();
        return "ip_" + ip; // 加前缀避免直接哈希冲突
    }

    @Override
    public long assignWorkerId() throws Exception {
        // 1. 读取或初始化 WorkerID 元数据
        WorkerMeta meta = readOrInitWorkerMeta();

        // 2. 检查 IP 是否变化（如果变化，需要重新生成 WorkerID）
        String currentIpHash = getIpHash();
        if (!currentIpHash.equals(meta.ipHash)) {
            System.err.println("WARN: IP changed! Old=" + meta.ipHash + ", New=" + currentIpHash);
            meta.ipHash = currentIpHash;
        }

        // 3. 计算 WorkerID
        meta.sequence++; // 增加顺序号
        int workerId = (Math.abs(meta.ipHash.hashCode()) % (MAX_WORKER_ID - SEQUENCE_OFFSET)) + (meta.sequence * SEQUENCE_OFFSET);

        // 4. 更新元数据文件
        meta.lastWorkerId = workerId;
        saveWorkerMeta(meta);
        return workerId;
    }

    // WorkerID 元数据类
    private static class WorkerMeta {
        int lastWorkerId;
        int sequence;
        String ipHash;

        WorkerMeta(int lastWorkerId, int sequence, String ipHash) {
            this.lastWorkerId = lastWorkerId;
            this.sequence = sequence;
            this.ipHash = ipHash;
        }
    }
}
